/******************************************************************************
 * 
 * Announce: CSharpKit, Basic algorithms, components and definitions.
 *           Copyright (C) ShenYongchen.
 *           All rights reserved.
 *   Author: 申永辰.郑州 (shenyczz@163.com)
 *  WebSite: http://github.com/shenyczz/CSharpKit
 *
 * THIS CODE IS LICENSED UNDER THE MIT LICENSE (MIT).
 * THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 
 * ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
 * IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
 * PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
 * 
******************************************************************************/

namespace CSharpKit.SVM
{
    /// <summary>
    /// Q matrices for various formulations
    /// SVC_Q
    /// </summary>
    internal class QM_SVC : Kernel
    {
        public QM_SVC(SvmProblem prob, SvmParameter param, sbyte[] y_)
            : base(prob.Count, prob.X, param)
        {
            y = (sbyte[])y_.Clone();
            cache = new Cache(prob.Count, (long)(param.CacheSize * (1 << 20)));
            QD = new double[prob.Count];
            for (int i = 0; i < prob.Count; i++)
                QD[i] = KernelFunction(i, i);
        }

        private readonly sbyte[] y;
        private readonly Cache cache;
        private readonly double[] QD;



        public override float[] GetQ(int i, int len)
        {
            float[] data;
            int start, j;
            if ((start = cache.GetData(i, out data, len)) < len)
            {
                for (j = start; j < len; j++)
                    data[j] = (float)(y[i] * y[j] * KernelFunction(i, j));
            }
            return data;
        }

        public override double[] GetQD()
        {
            return QD;
        }

        public override void SwapIndex(int i, int j)
        {
            cache.SwapIndex(i, j);
            base.SwapIndex(i, j);
            do { sbyte _ = y[i]; y[i] = y[j]; y[j] = _; } while (false);
            do { double _ = QD[i]; QD[i] = QD[j]; QD[j] = _; } while (false);
        }

        // void swap_index(int i, int j) const
        // {
        //     cache->swap_index(i, j);
        //     Kernel::swap_index(i, j);
        //     swap(y[i], y[j]);
        //     swap(QD[i], QD[j]);
        // }



        //}}@@@
    }



}
